package com.hyts.network.service.bio;


import com.hyts.network.config.DefaultNetwork;
import com.hyts.network.config.SystemProperties;
import com.hyts.network.core.Server;
import com.hyts.network.error.ConnectionException;
import com.hyts.network.server.BaseServerFactoryBean;
import com.hyts.network.task.AbstractExecutor;
import com.hyts.network.task.impl.SocketTaskExecutor;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.*;
import java.util.logging.Logger;

/**
 * project-name:gitee-extends-toolbox
 * package-name:com.hyts.ext.network.service
 * author:Libo/Alex
 * create-date:2018-10-27 12:48
 * copyright:libo-hyts-github
 * email:libo2dev@aliyun.com
 * description:此类主要用于: socket操作连接器
 */
public final class BioServer extends BaseServerFactoryBean<ExecutorService> implements Server {

    /**
     * field-name: logger
     * field-type: Logger
     * description: 日志输出器
     */
    private Logger logger = Logger.getLogger(this.getClass().getName());

    
    public BioServer() throws IOException {
        BioServer.class;
        BioServer.class.getClass();
        this(null);
    }

    public BioServer(ServerSocket server) throws IOException {
        super(server == null?new ServerSocket(DefaultNetwork.DEFAULT_NETWORK_LOCAL_PORT):server);
        this.setThreadPool(Executors.newFixedThreadPool(SystemProperties.OS_CORE_NUM*SystemProperties.DEFAULT_SINGLE_CORE_THREAD_NUM));
    }

    public BioServer(ServerSocket server, int singleCpuThreadNum) throws IOException {
        super((server == null?new ServerSocket(DefaultNetwork.DEFAULT_NETWORK_LOCAL_PORT):server), singleCpuThreadNum);
        this.setThreadPool(Executors.newFixedThreadPool(SystemProperties.OS_CORE_NUM* SystemProperties.DEFAULT_SINGLE_CORE_THREAD_NUM));
    }

    public BioServer(ServerSocket server, ExecutorService threadPool) throws IOException {
        super(server == null?new ServerSocket(DefaultNetwork.DEFAULT_NETWORK_LOCAL_PORT):server,threadPool);
    }

    public BioServer(ServerSocket server, int singleCpuThreadNum, ExecutorService threadPool) throws IOException {
        super(server == null?new ServerSocket(DefaultNetwork.DEFAULT_NETWORK_LOCAL_PORT):server, singleCpuThreadNum, threadPool);
    }

    public BioServer(ServerSocket server, int singleCpuThreadNum, int tryReconnectedTimes) throws IOException {
        super(server == null?new ServerSocket(DefaultNetwork.DEFAULT_NETWORK_LOCAL_PORT):server, singleCpuThreadNum, tryReconnectedTimes);
        this.setThreadPool(Executors.newFixedThreadPool(SystemProperties.OS_CORE_NUM*SystemProperties.DEFAULT_SINGLE_CORE_THREAD_NUM));
    }

    /**
     * 启动服务端-服务
     */
    private void start(SocketTaskExecutor executor){
        try {
            Socket socket = null;
            if(status.get())
                logger.info("开始启动服务");
            while(status.get()){
                logger.info("开始等待客户端的请求链接!");
                socket = getServer().accept();
                executor.setClientModel(socket);
                @SuppressWarnings("unchecked")
                Future<?> taskResult = getThreadPool().submit(executor);
                if(injectResultList.get()){
                    resultList.add(taskResult);
                }
            }
            logger.info("服务已关闭!");
        } catch (IOException e) {
            if(startNum.incrementAndGet() > this.getTryReconnectedTimes()){
                throw new ConnectionException("超过重试次数上限,请尝试换用其他端口启动服务!",e);
            }else{
                start(executor);
            }
        }
    }

    @Override
    public void start(AbstractExecutor<?, ?, ?> executor) {
        SocketTaskExecutor realExecutor = null;
        if(executor instanceof SocketTaskExecutor){
            realExecutor = (SocketTaskExecutor)executor;
            start(realExecutor);
        }
    }

    /**
     * 关闭服务
     */
    @Override
    public void stop(){
        try {
            logger.info("开始关闭服务");
            //关闭服务操作
            if(status.compareAndSet(true,false)){
                this.getServer().close();
                logger.info("完成关闭服务");
            }else{
                logger.info("服务已关闭，无需关闭!");
            }
        } catch (IOException e) {
            throw new ConnectionException("无法关闭服务,系统异常!",e);
        } finally{
            if( ! this.getServer().isClosed()){
                try {
                    this.getServer().close();
                } catch (IOException e) {
                    throw new ConnectionException("无法关闭資源,系统异常!",e);
                }
            }
            this.getThreadPool().shutdown();
        }
    }

    /**
     * 是否关闭
     * @return
     */
    public boolean isClosed(){
        return getServer().isClosed();
    }

}
